Skip to content

docs(skills): correct 8 false behavioral facts in objectstack-api (sweep flight ⑦) - #13827

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-13814-skills-sweep-api
Aug 31, 2026
Merged

docs(skills): correct 8 false behavioral facts in objectstack-api (sweep flight ⑦)#13827
os-zhuang merged 1 commit into
mainfrom
claude/issue-13814-skills-sweep-api

Conversation

@huangyiirene

Copy link
Copy Markdown
Collaborator

Fixes #13814
Part of #13658

Flight ⑦ of the published-skills factual sweep: skills/objectstack-api/** (3 files, 707 lines). Every behavioral claim was located in the implementing code first — never verified against another document — and the behavior-bearing ones were settled with executed probes. 8 distinct false facts across 9 landing sites, all in SKILL.md. evals/README.md and the generator-owned references/_index.md came back clean.

Landing sites — 落点 | before | after

# 落点 before after
1 SKILL.md:376 dispatcher table header HTTP Status | Error Type | When HTTP Status | Error Code | When
2 SKILL.md:548-550 best practice 3 error: { code, message, type?, … }, code is the numeric HTTP status error: { code, message, httpStatus?, … }, code is the semantic string
3 SKILL.md:393-395 handler-status note "Always set handlerStatus… The dispatcher returns 501 NOT_IMPLEMENTED for stub and planned handlers" "handlerStatus is DOCUMENTATION — nothing reads it at runtime. The dispatcher's 501 NOT_IMPLEMENTED comes from the endpoint executor, never from this field."
4 SKILL.md:557 best practice 5 "Set handlerStatus to communicate implementation progress to consumers." removed (nothing carries it to a consumer); items 6–7 renumbered 5–6
5 SKILL.md:409-410 websocket pointer "event delivery with filters" "event delivery (filters not enforced)"
6 SKILL.md:505 driver table mongo | Document store (MongoDB) mongodb | Document store (mongo is a legacy alias)
7 SKILL.md:507-508 driver table rows absent; turso described below the table as living outside the catalog sqlite-wasm and turso rows added; the two-line aside deleted
8 SKILL.md:520 IDataEngine "plus optional vectorFind/batch/execute" "plus optional vectorFind/execute"
9 SKILL.md:559-560 best practice 6 "upsert exists as an apiMethods enum value" "upsert is DERIVED (createupdate), not an apiMethods value"

Zero out-of-list changes. Site 4 is a deletion that both corrects a false claim and pays part of the token bill for sites 2, 5, 6 and 7 — the ceiling on this file had zero headroom, so every correction had to fund itself.

What each correction is settled against

1–2. error.type is gone and error.code is not a number. DispatcherErrorResponseSchema (packages/spec/src/api/dispatcher.zod.ts:189) declares code: z.string(), message, and httpStatus?; the type sibling was removed in the #3842 consolidation, which moved the numeric status to httpStatus and put the semantic spelling in code. Both directions executed: a body with code: 404 fails to parse, a body with code: 'ROUTE_NOT_FOUND' parses, and a body supplying type comes back with keys ["code","message","httpStatus"] — the key is stripped. The table header at site 1 named the same removed field.

3–4. handlerStatus has no runtime consumer. Repo-wide, excluding skills/** and tests, the identifier appears three times and all three are inside its own declaring file (packages/spec/src/api/plugin-rest-api.zod.ts:177, :1415, :1431). The dispatcher's NOT_IMPLEMENTED is emitted from four sites, all in the declarative-endpoint executor (packages/runtime/src/endpoint-executor.ts ×3, packages/runtime/src/api-mapping.ts ×1), and none reads the field. Nothing serializes it to a consumer either: RouteCoverageReportSchema is the only shape that would, and nothing constructs one. Filed for central triage as #13823 (the declared-but-inert key itself is an ADR-0049 enforce-or-remove question, not something a skill edit settles).

  1. WebSocket filters are declared, not enforced. packages/spec/src/api/websocket.zod.ts:55-78 records the measurement verbatim: no runtime ever evaluated an event filter, matchesSubscription matches on object name and event type only, and "a subscriber setting filters received every event regardless"; the key survives with a NOT-YET-ENFORCED marker because retiring it needs a tombstone and a conversion. The bullet two lines above already carried exactly that caveat for RealtimeEventType — this one did not, so the file taught enforcement on one inert key and warned about the other.

6–7. The driver catalog was one wrong spelling and two missing rows. Executed: BUILTIN_DRIVER_IDS is ["memory","sqlite","sqlite-wasm","postgres","mysql","mongodb","turso"], and resolveDriverId('mongo') answers 'mongodb'. The canon was renamed in #6345 — both boot hosts, the npm package and every URL scheme said mongodb — with the ADR-0087 conversion datasource-driver-mongo-to-mongodb converging stored rows; mongo survives only as an alias. turso became a full builtin row in the same change (it now ships TursoConfigSchema), so presenting it below the table as available "via the separate package" put a registered catalog id outside the catalog the heading promises.

  1. IDataEngine.batch was retired. The tombstone is at packages/spec/src/contracts/data-engine.ts:280-288: ADR-0119 D3 (chore(spec): retire IDataEngine.batch? per ADR-0119 D3 — declared-but-unimplemented, zero callers #4618) removed it — never implemented by any engine, never called, and it specified nothing about partial failure, ordering, cross-object references or rollback scope. The live members are find/findOne/insert/update/delete/count/aggregate plus optional vectorFind/execute (:224-296).

  2. upsert is not an apiMethods value. Executed: ApiMethod.options is ["get","list","create","update","delete","bulk"] and 'upsert' is not in it; it sits in LEGACY_API_METHODS, stripped at parse by stripLegacyApiMethods, and derives from create ∧ update. This also contradicted the file's own API Methods section 270 lines earlier, which states the six-primitive rule correctly — a cross-section contradiction settled against the implementation, not against either sentence.

Executed evidence (non-vacuity control)

One probe file, run under the shared verify lock, 30+ assertions against packages/spec sources. Beyond the four falsehood proofs above:

authRequired omitted -> parsed authRequired = true
authRequired:false + {windowMs,maxRequests}  -> D6 rejection   (RateLimitConfigSchema.parse({windowMs,maxRequests}).enabled = false)
authRequired:false + {enabled:true,...}      -> []  (accepted)
outputMapping[].transform / inputMapping on a 'find' op / targets 'x' and 'x.y' / type:'script' / path outside the carve-out  -> one rejection each
['list']            -> ["list","aggregate","search","export"]
['create','update'] -> ["create","update","upsert","import"]
[]                  -> mode "deny-all", operations []
API_OPERATION_ORDER.length = 14
ServiceStatus.options    = ["available","registered","unavailable","degraded","stub"]   ('healthy' rejected)
AuthProvider.options     = ["local","google","github","microsoft","ldap","saml"]
TransportProtocol.options= ["websocket","sse","polling"]

Every one of those confirms a sentence the skill already had right, which is what makes the eight corrections a measurement rather than a hunt.

Verified clean, worth naming

  • evals/README.md — all ten rubric descriptions check out against the implementation (the /data prefix, aggregation through POST /data/{object}/query with no GET .../aggregate, per-object vs cross-object batch, the flat { error, code } data-route bodies with CONCURRENT_UPDATE → 409 and VALIDATION_FAILED → 400, the RestApiEndpointSchema shape, the object_operation/flow-only execution set, the carve-out, the authRequired default and the D6 armed-budget rule). Flight ③ found rubrics teaching graders to fail correct answers; this package's do not.
  • references/_index.mdcheck:skill-refs reports all 9 generated files in sync, and every one of the 23 pointers resolves to a file that exists and is inside the published files glob (src/**/*.zod.ts). Not hand-edited.
  • The whole declarative-endpoint chapter — five publish gates, their order, the carve-out, D6, the three mapping rules, the object_operation/flow pipeline targets — is accurate line for line against endpoint-publish-gate.ts and the runtime modules it mirrors.

One nuance deliberately NOT added

SKILL.md:363 says /ready "returns 200 only when the kernel is fully running, and 503 while booting or shutting down". Both halves are true, but since #13408 (today) /ready also answers 503 when the primary datasource driver is unhealthy. The sentence is incomplete, not false, and the ceiling has 8 tokens of headroom — so under the program's rule this is nuance overflow for content/docs/**, not new text for ratcheted skill prose. Recorded here rather than silently skipped. (The same staleness sits in a code comment at packages/runtime/src/dispatcher-plugin.ts:977-979.)

Budget — both readings

reading before after delta
whole file skills/objectstack-api/SKILL.md, lines 609 607 −2
whole file, tokens (ratchet convention) 6319 6311 −8
package-wide, all 11 published skills/*/SKILL.md, lines 10503 10501 −2
package-wide, tokens 117856 117848 −8

Ceilings unchanged. check-skills-token-ratchet.mjs was red at exit 1 on the first draft (6364 tokens, over by 45) and the corrections were tightened and paid for until it went green with headroom 8 — no ceiling was touched, which is maintainer-only.

Gates — all readings at 5a5804ae

Families derived from the real diff with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (1 path, no STALE warning; re-derived after the commit and the list is byte-identical). 14 families, exit codes captured before any pipe:

0  node scripts/check-ci-filter-parity.mjs
0  node scripts/check-cross-package-test-inputs.mjs
0  node scripts/check-shard-attestation.mjs
0  node scripts/check-skills-token-ratchet.mjs
3  node scripts/check-test-completeness.mjs          <- PREREQUISITE NOT MET, see below
0  pnpm --filter @objectstack/lint run check:doc-formula-expressions
0  pnpm check:agent-test-spelling
0  pnpm check:corpus-claim-drift
0  pnpm check:cross-package-test-inputs
0  pnpm check:doc-authoring
0  pnpm check:pm-governed-merges
0  pnpm check:role-word
0  pnpm check:skill-compatibility
0  pnpm check:skill-frame-sync

Plus, outside the derived list: pnpm --filter @objectstack/spec check:skill-refs exit 0 ("9 generated files in sync"), and a control-character scan of the diff (grep -naP over the C0 set) with no hits.

  • check-test-completeness.mjs exit 3 is its own PREREQUISITE-NOT-MET code: it grades a saved turbo run test log that only CI produces, and its message says so — "the local reading for this gate is NOT MEASURED… it is not a red". Recorded as NOT MEASURED.
  • check:doc-formula-expressions first exited 1 on the same prerequisite branch (@objectstack/formula and @objectstack/lint unbuilt). Both were built and it was re-run to a real exit 0; the first reading is reported as not-measured rather than as a failure.

Declared narrowing — check:skill-examples. The path derivation does not name this family for skills/**, and the diff's population for it is empty, measured three ways rather than assumed: ① the gate's own population is os:check-marked fences (packages/spec/scripts/check-skill-examples.ts); ② this file has 6 such fences, at lines 123-138, 171-185, 328-340, 438-446, 480-495 and 529-538, and the diff's hunks are at 376, 393-395, 409-411, 505-510, 520, 548-551, 557 and 559-561 — disjoint, zero overlap; ③ a fence's verdict is a function of its own text and the spec/client-react declaration types, neither of which this diff changes, so no untouched fence's verdict can move. Running it locally needs a @objectstack/client-react build; CI runs it regardless.

Posture

Published skills/** is governed: this PR stays DRAFT for a human merge, and needs:contract-review is attached to it and to card #13814 in the same stroke. Pure skills/** diff, nothing published from a package, so skip-changeset applies.

Generated by Claude Code


Generated by Claude Code

Flight ⑦ of the published-skills factual sweep (program #13658). Every claim
verified against the implementing code plus executed probes; corrections are
byte-neutral-or-shrinking under the token ratchet (net -8 tokens / -2 lines).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EnE7G31tqbxN1rqpQmzurT
@huangyiirene huangyiirene added skip-changeset PR has no user-facing published change; bypasses the changeset gate needs:contract-review labels Aug 31, 2026 — with Claude
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Aug 31, 2026

Copy link
Copy Markdown
Collaborator Author

Contract review — PASS at head 5a5804ae

Applicability: clause-② CONTENT limb (批 #12). Both carriers attached at PR creation (PR + card #13814), read back; cleared in this stroke.

Reviewer qualification, machine-read this sitting: get_sessionexternal_metadata.last_served_model = claude-fable-5 = CONTRACT_REVIEW_TIER. Dispatching-seat review per the 2026-08-21 relaxation.

Review: report + diff read; anchors independently re-measured on origin/main this hour —

  • packages/spec/src/api/contract.test.ts:661–665 pins httpStatus as the numeric-status carrier — error.code is the semantic string, the skill's numeric-code claim was false;
  • packages/spec/src/conversions/conversions.test.ts:718: resolveDriverId('mongo') === 'mongodb' — the canonical-id correction and catalog completion (sqlite-wasm, turso in DRIVER_VOCABULARY) match the registry;
  • packages/spec/src/data/object.zod.ts:18–20: ApiMethod enum carries the six primitives, upsert absent — the in-file contradiction settled against the implementation, correctly;
  • handlerStatus greps to declaring file + generated surface JSON + docs + the skill itself and NO runtime package — the executed probe showed the 501 emitted from sites that never read it, and finding(spec): RestApiEndpointSchema.handlerStatus is authorable but has zero runtime consumers — the 501 it is documented to cause comes from somewhere else #13823's zero-consumer premise holds (ADR-0049 enforce-or-remove class, filed with both routes laid out for triage);
  • The dispatcher error probe (numeric code refused, semantic string accepted, supplied type stripped on parse-back) proves the falsehoods rather than reading them.

Instrument notes accepted: the zero-hit "silently/ignored/dropped" seed recorded as a real zero (with the package simply not carrying that class); the check:skill-examples empty-diff-population narrowing declared with three measurements; the first-draft ratchet red (over by 45) paid down to −8 tokens without touching a ceiling — the farm shaping the fix, recorded. The /ready incompleteness routed to content/docs follow-ups instead of ratcheted prose is the program's own overflow rule applied right.

needs:contract-review cleared on BOTH carriers. Governed .md content: PR remains DRAFT for the maintainer's merge (os-zhuang / hotlong requested).


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

skills-sweep ⑦: objectstack-api (707 lines, 3 files) — behavioral-claim verification, content-class execution-first

3 participants